#
# "@(#) $Id: SourceView.py,v 1.1.1.1 2006-07-27 03:16:08 gioshe Exp $"
#
# This work is released under the GNU GPL, version 2 or later.
#
from Utils.kdeemul import *
from DB.Playlist import *
from DB.Library import *
from CD.CDROM import *
from DB.CDLibrary import *
###GTD:: from PodLibrary import *
from Services.Sharing import *

from TrackDrag import *
from PlaylistDrag import *
from RemoteTrackDrag import *
from RemotePlaylistDrag import *

from SourceViewItem import *
from TrashSourceViewItem import *
from SharedPlaylistSourceViewItem import *
from SharedPlaylistsSourceViewItem import *
#from SlimServerSourceViewItem import *
from StationsSourceViewItem import *
from CDDVDSourceViewItem import *
from SmartPlaylistSourceViewItem import *
from PlaylistSourceViewItem import *
###GTD:: from PodDeviceSourceViewItem import *
from LibrarySourceViewItem import *
from EncoderSourceViewItem import *
from Utils.Settings import *

def removeDuplicates(items):
	result = {}
	for item in items:
		result[str(item)] = 1
	return result.keys()

def cmpRect(r1,r2):
	if r1.x()!=r2.x(): return False
	if r1.y()!=r2.y(): return False
	if r1.width()!=r2.width(): return False
	if r1.height()!=r2.height(): return False
	return True


class SourceView(QListView):
	def __init__(self,container,mainWindow):
		QListView.__init__(self,container,"sources")
		backColor=QColor(Settings.settings().get('ColorR'),Settings.settings().get('ColorG'),Settings.settings().get('ColorB'))
		self.setPaletteBackgroundColor(backColor)
		self.library = Library.mainLibrary()
		self.cdSources = []
		self.dellSource = None
		self.ipodSource = None
		self.encoderSource = None
		self._hasDDJ = False
		self.loadHeaders()
		self.loadSources()
		self.connect(self,SIGNAL("clicked(QListViewItem *)"),self.selectSourceItem)
		self.library.connect(PYSIGNAL("addedPlaylist"),self.addedPlaylist)
		self.library.connect(PYSIGNAL("removedPlaylist"),self.removedPlaylist)
		#self.library.connect(PYSIGNAL("renamedPlaylist"),self.renamedPlaylist)
		QObject.connect(self,PYSIGNAL("dropped(QDropEvent *, QListViewItem *)"),self.droppedOnItem)
		#QObject.connect(self,SIGNAL("dropped(QDropEvent *, QListViewItem *)"),self.droppedOnItem)
		QObject.connect(self,SIGNAL("doubleClicked(QListViewItem *)"),self.doDoubleClicked)
		QObject.connect(self,SIGNAL("contextMenuRequested(QListViewItem *, const QPoint &, int)"),self.contextMenu)
		self.setAcceptDrops(True)
		self.setTreeStepSize(10)
		self.viewport().setAcceptDrops(True)
		#self.setDropVisualizer(False)
		#self.setDropHighlighter(True)
		self.setDefaultRenameAction(QListView.Accept)
		QObject.connect(CDLibraries.singleton(),PYSIGNAL("cdMounted"),self.cdMounted)
		#QObject.connect(CDROM.singleton(),PYSIGNAL("cdEjected"),self.cdEjected)
		###GTD:: PodLibrary.singleton().connect(PYSIGNAL('ipodMounted'),self.ipodInserted)
		###GTD:: PodLibrary.singleton().connect(PYSIGNAL('ipodUnmounted'),self.ipodEjected)
		EncoderLibrary.singleton().playlist.connect(PYSIGNAL("addedTrack"),self.addedEncoderTrack)
		EncoderLibrary.singleton().playlist.connect(PYSIGNAL("removedTrack"),self.removedEncoderTrack)		
		self.mOldDropHighlighter = QRect(0,0,0,0)
		self.mainWindow = mainWindow
		
		self.oldCurrent = 0
		self.dropItem = 0
		self.autoOpenTime = 750
		self.openTimer = QTimer(self)
		self.flashTimer = QTimer(self)
		self.connect(self.openTimer,SIGNAL("timeout()"),self.openFolder)
		self.connect(self.flashTimer,SIGNAL("timeout()"),self.flashFunc)
		self.flashing = False
		self.flashCount = 0
		self.flashItem = None
		self.fullWidth = False
		
		self.eighttrak = []
		self.slimp3s = []

		self.sharing = Sharing.singleton()
		QObject.connect(self.sharing,PYSIGNAL('addSlimp3Service'),self.addSlimp3)
		QObject.connect(self.sharing,PYSIGNAL('removeSlimp3Service'),self.removeSlimp3)
		QObject.connect(self.sharing,PYSIGNAL('addService'),self.addShared)
		QObject.connect(self.sharing,PYSIGNAL('removeService'),self.removeShared)
		
		Sharing.singleton().fromSettings()
		#PodLibrary.mount()
		

	def __del__(self):
		self.killTasks()

	def killTasks(self):
			pass

	def openFolder(self):
		self.openTimer.stop()
		if self.dropItem and not self.dropItem.isOpen():
			self.dropItem.setOpen(True)
			self.dropItem.repaint()
	
	def flashFunc(self):
		if self.flashCount == 6:
			self.flashTimer.stop()
			self.flashCount = 0
			return
		elif self.flashCount==0:
			self.flashTimer.start(50)
		self.flashCount = self.flashCount+1
		if self.flashing:
			self.flashing = False
			self.flashItem.setBackgroundColor(None)
			self.flashItem.repaint()
		else:
			self.flashing = True
			self.flashItem.setBackgroundColor(QColor(0,0,255))
			self.flashItem.repaint()
	
	def contentsDragEnterEvent(self,e):
		#print "drag enter"
		self.oldCurrent = self.currentItem()
		self.contentsDragMoveEvent(e)
	
	def contentsDragMoveEvent(self,e):
		#print "drag move"
		vp = self.contentsToViewport(e.pos())
		i = self.itemAt(vp)
		if i:
			#print "over item",i
			if i.acceptDrag(e):
				#print "accepting"
				e.accept(self.itemRect(i))
				if i!=self.dropItem:
					if self.dropItem:
						self.dropItem.setBackgroundColor(None)
						self.dropItem.repaint()
					i.setBackgroundColor(QColor(200,214,255))
					i.repaint()
					self.openTimer.stop()
					self.dropItem = i
					self.openTimer.start(self.autoOpenTime)
			else:
				if self.dropItem:
					self.dropItem.setBackgroundColor(None)
					self.dropItem.repaint()
					self.dropItem = 0
				#print "ignoring"
				e.ignore(self.itemRect(i))
		else:
			#print "over empty"
			if self.dropItem:
				self.dropItem.setBackgroundColor(None)
				self.dropItem.repaint()
			if self.acceptDrag(e): e.accept()
			else: e.ignore()
			self.openTimer.stop()
			self.dropItem = 0
	
	def contentsDragLeaveEvent(self,e):
		#print "drag leave"
		self.openTimer.stop()
		if self.dropItem:
			self.dropItem.setBackgroundColor(None)
			self.dropItem.repaint()
			self.dropItem = 0
		self.setCurrentItem(self.oldCurrent)
		self.setSelected(self.oldCurrent,True)
	
	def contentsDropEvent(self,e):
		#print "drag drop"
		self.openTimer.stop()
		if self.dropItem:
			self.dropItem.setBackgroundColor(None)
			self.dropItem.repaint()
			self.dropItem = 0
		item = self.itemAt(self.contentsToViewport(e.pos()))
		if item:
			#print "dropped on item",item
			if item.acceptDrag(e) and item.dropped(e):
					#print "accepted"
					self.flashItem = item
					self.flashFunc()
		elif self.acceptDrag(e):
			self.dropped(e)
	
	def setFullWidth(self,bool = True):
		self._fullWidth = bool
		self.header().setStretchEnabled(self.fullWidth(),self.columns()-1)
	
	def fullWidth(self):
		return self._fullWidth

	def selectSourceItem(self,item):
		if item:
			item.select(self)
		#self.selectSource(str(item.text(0)))

	def selectSource(self,source):
		#print("hit source "+str(source))
		self.emit(PYSIGNAL("selectSource"),(source,None))

	def loadHeaders(self):
		self.addColumn(i18n("Media"))
		self.setFullWidth(True)
		self.setSelectionMode(QListView.Single)
		#self.setRootIsDecorated(True)

	def loadSources(self):
		self.cdSources = []
		self.dellSource = None
		self.clear()
		playlists = self.library.playlists
		self.loadSharedSources()
		self.loadEncoder()
		StationsSourceViewItem(self)
		for playlist in playlists:
			self.addPlaylistItem(playlist)
		#SharedPlaylistSourceViewItem(self,"Joe's Shared Music")
		#DeviceSourceViewItem(self,"Jane's Player")

	def addPlaylistItem(self,playlist):
		if playlist.master:
			self.master = LibrarySourceViewItem(self,playlist)
		elif playlist.trash:
			TrashSourceViewItem(self.master)
		elif playlist.smart:
			SmartPlaylistSourceViewItem(self.master,playlist)
		else:
			PlaylistSourceViewItem(self.master,playlist)
		self.setOpen(self.master,True)
	
	def loadRemoveables(self):
		#if self.hasCD():
		#	self.cdInserted()
		pass

	def addedPlaylist(self,library,playlist):
		#self.loadSources()
		#self.loadRemoveables()
		self.addPlaylistItem(playlist)
		item = self.findItem(playlist.name,0)
		if item:
			#print "starting rename of",item
			item.startRename(0)
		
	def removedPlaylist(self,library,playlist):
		#print "removing",playlist.name
		item = self.findItem(playlist.name,0)
		if item:
			if item.isSelected():
				self.setSelected(self.master,True)
				self.master.select(self)
			#self.master.setOpen(False)
			self.master.takeItem(item)
			del item

	def renamedPlaylist(self,oldName,newName):
		self.loadSources()
		self.loadRemovables()

	def droppedOnItem(self,event,item):
		pos = self.contentsToViewport(event.pos())
		saveSelectedItem = self.selectedItem()
		item = self.itemAt(pos)
		if item:
			item.dropped(event)
		# XXX DSM workaround for Qt bug?
		self.repaint()
		if saveSelectedItem:
			try: # it might have been destroyed!
				#print "attempting refresh of",saveSelectedItem.text(0)
				self.setSelected(saveSelectedItem,False)
				self.setSelected(saveSelectedItem,True)
			except: pass

	#
	# handle the creation of playlists by drags into empty areas
	#
	def dropped(self,event):
		print "dropped in empty area"
		if TrackDrag.canDecode(event):
			#print "trackIDs dropped nowhere"
			drag = TrackDrag.decode(event)
			trackIDs = drag['TrackIDs']
			self.library.addPlaylistFromTrackIDs(trackIDs)
		elif LRemotePlaylistDrag.canDecode(event):
			print "accepting remote playlist drag"
			drag = LRemotePlaylistDrag.decode(event)
			newName = self.library.uniquePlaylistNameFrom(drag['Name'])
			print "creating new playlist",newName
			playlist = self.library.addNewPlaylist(newName)
			tracks = []
			for trackplist in drag['Playlist Items'].values():
				track = Track()
				track.setPList(trackplist)
				tracks.append(track)
			Services.Downloader.singleton().downloadTracks(tracks,playlist,self.library)
		elif LRemoteTrackDrag.canDecode(event):
			drag = LRemoteTrackDrag.decode(event)
			tracks = []
			for trackplist in drag['Tracks']:
				track = Track()
				track.setPList(trackplist)
				tracks.append(track)
			name = self.library.uniquePlaylistNameFromTracks(tracks)
			playlist = self.library.addNewPlaylist(name)
			Services.Downloader.singleton().downloadTracks(tracks,playlist,self.library)
		# XXX DSM handle file drags here?

	def acceptDrag(self,event):
		#print "can accept in empty area?"
		if TrackDrag.canDecode(event): return True
		if LRemotePlaylistDrag.canDecode(event): return True
		if LRemoteTrackDrag.canDecode(event): return True
		# XXX DSM handle file drags here?
		return False

	def dragObject(self):
		selectedItem = self.selectedItem()
		if selectedItem:
			drag = selectedItem.createDrag(self)
			if drag: drag.dragCopy()

	def doDoubleClicked(self,item):
		item.doubleClick()

	def contextMenu(self,item,pos,column):
		if item!=None and item.hasContextMenu:
			item.contextMenu(pos,column,self.mainWindow)
		#self.doDoubleClicked(item)
		#self.popup.exec_loop(pos)

	def hasCD(self):
		return CDROMS.singleton().hasCD()
		
	def cdMounted(self,library,firstTime = False):
		cdSource = CDDVDSourceViewItem(self,library)
		self.cdSources.append(cdSource)
		QObject.connect(library.drive,PYSIGNAL('cdEjected'),self.cdEjected)
		action = Settings.settings().get("CD Insertion Action","show")
		if not firstTime:
			if action=='show' or action=='play':
				self.setSelected(cdSource,True)
				cdSource.select(self)

	def cdEjected(self,drive):
		for cdSource in self.cdSources:
			if cdSource.library.drive==drive:
				QObject.disconnect(drive,PYSIGNAL('cdEjected'),self.cdEjected)
				if cdSource.isSelected:
					self.setSelected(self.master,True)
					self.master.select(self)
				self.takeItem(cdSource)
				self.cdSources.remove(cdSource)
				del cdSource
				break

	def ipodInserted(self):
		if self.ipodSource==None:
			self.ipodSource = LPodDeviceSourceViewItem(self)
	
	def ipodEjected(self):
		if self.ipodSource:
			if self.ipodSource.isSelected():
				self.setSelected(self.master,True)
				self.master.select(self)
			self.takeItem(self.ipodSource)
			del self.ipodSource
			self.ipodSource = None			
	def showSongSource(self,track,library,playlist):
		item = self.firstChild()
		while item:
			if item.source == playlist:
				self.setSelected(item,True)
				item.select(self)
				return True
			item = item.itemBelow()
		return False

	def loadSharedSources(self):
		shares = Sharing.singleton().shares()
##		slimp3s = shares['slimp3']
##		for s in slimp3s.values():
##			self.addSlimp3(s['Name'],s['Type'],s['Address'],s['Port'])
		eighttrak = shares['lsongs']
		for s in eighttrak.values():
			self.addShared(s['Name'],s['Type'],s['Address'],s['Port'])
			
	def addSlimp3(self,name,type,address,port):
		slimp3 = SlimServerSourceViewItem(self,name,type,address,port)
		self.slimp3s.append(slimp3)

	def removeSlimp3(self,name,type):
		#print "removing slimp3",name
		for slimp3 in self.slimp3s:
			if slimp3.name == name:
				try:
					if slimp3.isSelected():
						self.setSelected(self.master,True)
						self.master.select(self)
					self.takeItem(slimp3)
					self.slimp3s.remove(slimp3)
					break
				except: pass

	def addShared(self,name,type,address,port):
		#print "adding shared eighttrak",name
		eighttrak = SharedPlaylistsSourceViewItem(self,name,type,address,port)
		self.eighttrak.append(lsongs)
	
	def removeShared(self,name,type = '_eighttrak._tcp'):
		#print "removing shared eighttrak",name
		for eighttrak in self.lsongs:
			if eighttrak.name == name:
				try:
					if eighttrak.isSelected() or lsongs.isChildSelected():
						self.setSelected(self.master,True)
						self.master.select(self)
					self.takeItem(eighttrak)
					self.eighttrak.remove(lsongs)
					break
				except: pass

	def addedEncoderTrack(self,playlist,id):
		#print "SourceView: added encoder track",id,playlist,self.encoderSource
		if self.encoderSource==None:
			self.encoderSource = LEncoderSourceViewItem(self)
			#print "added"
	
	def removedEncoderTrack(self,playlist,id):
		#print "SourceView: removed encoder track"
		if self.encoderSource:
			if playlist.trackCount()==0:
				if self.encoderSource.isSelected():
					self.setSelected(self.master,True)
					self.master.select(self)
				self.takeItem(self.encoderSource)
				del self.encoderSource
				self.encoderSource = None
				#print "removed"
	
	def loadEncoder(self):
		#print "attempting to mount encoder source"
		if EncoderLibrary().singleton().playlist.trackCount()>0 and self.encoderSource==None:
			self.encoderSource = LEncoderSourceViewItem(self)
	
	#
	# The following three routines are a workaround to a bug
	# in KDE 3.1 when highlighting items that are a drop target
	# They attempt to overload the drop visualizer position to
	# also indicate the drop highlight position. Unfortunately,
	# these should be different items. The main reason we
	# have to override so much is that the highlight rectangle
	# is stored in some private structures within the KListView
	# instance
	#
	# This is a not a complete fix - I have made no attempt to
	# preserve the behavior of the drop visualizer since I don't
	# need it.
	#
##~ 	def contentsDragMoveEvent(self,event):
##~ 		pos = self.contentsToViewport(event.pos())
##~ 		if self.acceptDrag(event):
##~ 			event.acceptAction()
##~ 			if self.dropHighlighter():
##~ 				item = self.itemAt(pos)
##~ 				tmpRect = self.drawItemHighlighter(None, item)
##~ 				if not cmpRect(tmpRect,self.mOldDropHighlighter):
##~ 					self.cleanItemHighlighter()
##~ 					self.mOldDropHighlighter=tmpRect
##~ 					self.viewport().repaint(tmpRect)
##~ 		else:
##~ 			self.cleanItemHighlighter()
##~ 			event.ignore()
##~ 
##~ 	def cleanItemHighlighter(self):
##~ 		if self.mOldDropHighlighter.isValid():
##~ 			rect = self.mOldDropHighlighter
##~ 			self.mOldDropHighlighter = QRect()
##~ 			self.viewport().repaint(rect, True)
##~ 
##~ 	def viewportPaintEvent(self,e):
##~ 		QListView.viewportPaintEvent(self,e)
##~ 		if self.mOldDropHighlighter.isValid() and e.rect().intersects(self.mOldDropHighlighter):
##~ 			painter = QPainter(self.viewport())
##~ 			self.style().drawPrimitive(QStyle.PE_FocusRect, painter, self.mOldDropHighlighter, self.colorGroup(),QStyle.Style_FocusAtBorder)

